﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using DevExpress.XtraEditors.Repository;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Security.Permissions;
using System.Collections;
using ProgNetUtils;
using System.ComponentModel.Design.Serialization;
using DevExpress.XtraEditors;
using System.Runtime.Serialization;
using ProgNetExtensions.ExtenderProviders.Serialization;
//using ProgNetExtensions.TypeConverters;
//using ProgNetExtensions.Editors;
using System.Drawing.Design;

namespace ProgNetExtensions.ExtenderProviders
{
    

    [ProvideProperty("DataProviderName", typeof(object))]
    public class DataSourceProvider : Component, IExtenderProvider, ISupportInitialize
    {
        private bool isInitialized = false;
        private Hashtable nameObjects;
        private Hashtable providerObjects;

        private ContainerControl parentControl;
        [DefaultValue((string)null)]
        [Browsable(false)]
        public ContainerControl ContainerControl
        {
            [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows), UIPermission(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
            get { return parentControl; }
            set
            {
                parentControl = value;
            }
        }

        public override ISite Site
        {
            get
            {
                return base.Site;
            }
            set
            {
                base.Site = value;
                if (value != null)
                {
                    IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (host != null)
                    {
                        IComponent component = host.RootComponent;
                        if (component is ContainerControl)
                        {
                            ContainerControl = component as ContainerControl;
                        }
                    }
                }
            }
        }

        //[TypeConverter(typeof(DataProviderNametypeConverter))]
        [Editor("ProgNetExtensions.Editors.DataProviderNameEditor", typeof(UITypeEditor))]
        public void SetDataProviderName(object sender, string value)
        {
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                nameObjects[sender.GetObjectName()] = value;
                providerObjects[sender.GetObjectName()] = DataProviderTools.DataProviderCache.Instance.getProvider(value);
            }
            else
            {
                nameObjects[sender] = value;
                RepositoryItemLookUpEditBase properties = sender as RepositoryItemLookUpEditBase;
                if (properties != null)
                {
                    properties.NullValuePrompt = "";
                    properties.NullText = "";
                }
                else
                {
                    LookUpEditBase edit = sender as LookUpEditBase;
                    if (edit != null)
                    {
                        edit.Properties.NullText = "";
                        edit.Properties.NullValuePrompt = "";
                    }
                }
            }
        }
        //[TypeConverter(typeof(DataProviderNametypeConverter))]
        [Editor("ProgNetExtensions.Editors.DataProviderNameEditor", typeof(UITypeEditor))]
        
        public string GetDataProviderName(object sender)
        {
            if (PnInitialization.IsAppRunning)
            {
                if (nameObjects.ContainsKey(sender.GetObjectName()))
                    return nameObjects[sender.GetObjectName()].AsString();
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                    return nameObjects[sender].AsString();
            }
            return string.Empty;
        }

        public DataProviderTools.DataProvider GetDataProvider(object sender)
        {
            if (PnInitialization.IsAppRunning)
            {
                if (providerObjects.ContainsKey(sender.GetObjectName()))
                {
                    return providerObjects[sender.GetObjectName()] as DataProviderTools.DataProvider;
                }
            }
            return null;
        }

        public DataSourceProvider()
        {
            nameObjects = new Hashtable();
            providerObjects = new Hashtable();
        }

        #region IExtenderProvider Members

        public bool CanExtend(object extendee)
        {
            if (extendee is RepositoryItemLookUpEditBase ||
                extendee is LookUpEditBase)
                return true;
            return false;
        }

        #endregion


        #region ISupportInitialize Members

        public void BeginInit()
        {
            isInitialized = false;
        }

        public void EndInit()
        {
            isInitialized = true;
            ReplaceObjectsByName();
        }
        private void ReplaceObjectsByName()
        {
            object[] objs = new object[nameObjects.Keys.Count];
            nameObjects.Keys.CopyTo(objs, 0);
            for (int i = 0; i < objs.Length; i++)
            {
                string name = objs[i].GetObjectName();
                if(name.IsNotEmpty()){
                    if (!nameObjects.ContainsKey(name))
                    {
                        nameObjects[name] = nameObjects[objs[i]];
                    }
                    nameObjects.Remove(objs[i]);
                }
            }

            objs = new object[providerObjects.Keys.Count];
            providerObjects.Keys.CopyTo(objs, 0);
            for (int i = 0; i < objs.Length; i++)
            {
                string name = objs[i].GetObjectName();
                if (name.IsNotEmpty())
                {
                    if (!providerObjects.ContainsKey(name))
                    {
                        providerObjects[name] = providerObjects[objs[i]];
                    }
                    providerObjects.Remove(objs[i]);
                }
            }
        }

        #endregion
    }
}
